package com.gitee.apanlh.web.content;

import com.gitee.apanlh.util.base.ObjectUtils;
import com.gitee.apanlh.util.base.SingletonUtils;
import com.gitee.apanlh.util.base.builder.MapBuilder;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.http.HttpContentType;
import com.gitee.apanlh.web.util.ServletUtils;
import jakarta.servlet.http.HttpServletRequest;

import java.util.Map;

/**
 * 	Request请求类型上下文
 * 
 * 	@author Pan
 */
public class RequestContentTypeContext {
	
	/** 获取请求类型 */
	static final Map<String, RequestContentStrategy> TYPE_STRATEGY = new MapBuilder.Builder<String, RequestContentStrategy>(16)
		.put(null, 													SingletonUtils.get(GetContentStrategy.class))
		.put(HttpContentType.APPLICATION_JSON.getType(), 			SingletonUtils.get(JsonContentStrategy.class))
		.put(HttpContentType.APPLICATION_JSON_UTF8.getType(), 		SingletonUtils.get(JsonContentStrategy.class))
		.put(HttpContentType.APPLICATION_FORM_URLENCODED.getType(), SingletonUtils.get(FormContentStrategy.class))
		.put(HttpContentType.APPLICATION_XML.getType(), 			SingletonUtils.get(XmlContentStrategy.class))
		.put(HttpContentType.MULTIPART_FORM_DATA.getType(), 		SingletonUtils.get(FormDataContentStrategy.class))
		
		.put(HttpContentType.APPLICATION_JAVASCRIPT.getType(), 		SingletonUtils.get(TextContentStrategy.class))
		.put(HttpContentType.TEXT_PLAIN.getType(), 					SingletonUtils.get(TextContentStrategy.class))
		.put(HttpContentType.TEXT_XML.getType(), 					SingletonUtils.get(TextContentStrategy.class))
		.put(HttpContentType.TEXT_HTML.getType(), 					SingletonUtils.get(TextContentStrategy.class))
		
		.put(HttpContentType.APPLICATION_OCTET_STREAM.getType(), 	SingletonUtils.get(FileStreamContentStrategy.class))
		.put(HttpContentType.APPLICATION_ZIP.getType(), 			SingletonUtils.get(FileStreamContentStrategy.class))
		.put(HttpContentType.IMAGE_JPEG.getType(), 					SingletonUtils.get(FileStreamContentStrategy.class))
	.build();
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private RequestContentTypeContext() {
		//	不允许外部实例
		super();
	}
	
	/**	
	 * 	是否为JSON类型
	 * 	
	 * 	@author Pan
	 * 	@param  request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isJson(HttpServletRequest request) {
		return isJson(request.getContentType());
	}
	
	/**	
	 * 	是否为JSON类型
	 * 	
	 * 	@author Pan
	 * 	@param  contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isJson(String contentType) {
		return hasType(TYPE_STRATEGY.get(contentType), HttpContentType.APPLICATION_JSON);
	}
	
	/**	
	 * 	是否为Form类型
	 * 	
	 * 	@author Pan
	 * 	@param 	request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isForm(HttpServletRequest request) {
		return isForm(request.getContentType());
	}
	
	/**	
	 * 	是否为Form类型
	 * 	
	 * 	@author Pan
	 * 	@param 	contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isForm(String contentType) {
		return hasType(TYPE_STRATEGY.get(contentType), HttpContentType.APPLICATION_FORM_URLENCODED);
	}
	
	/**	
	 * 	是否是文本类型
	 * 	
	 * 	@author Pan
	 * 	@param 	request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isText(HttpServletRequest request) {
		return isText(request.getContentType());
	}
	
	/**	
	 * 	是否是文本类型
	 * 	
	 * 	@author Pan
	 * 	@param 	contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isText(String contentType) {
		return hasType(TYPE_STRATEGY.get(contentType), HttpContentType.TEXT_PLAIN);
	}
	
	/**	
	 * 	是否是FORM-DATA类型
	 * 	
	 * 	@author Pan
	 * 	@param 	request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isFormData(HttpServletRequest request) {
		return isFormData(request.getContentType());
	}
	
	/**	
	 * 	是否是FORM-DATA类型
	 * 	
	 * 	@author Pan
	 * 	@param 	contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isFormData(String contentType) {
		FormDataContentStrategy formData = SingletonUtils.get(FormDataContentStrategy.class);
		return !ValidParam.isEmpty(formData.getContentStr(contentType));
	}
	
	/**	
	 * 	是否为文件流
	 * 	
	 * 	@author Pan
	 * 	@param 	request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isFileStream(HttpServletRequest request) {
		return isFileStream(request.getContentType());
	}
	
	/**	
	 * 	是否为文件流
	 * 	
	 * 	@author Pan
	 * 	@param 	contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isFileStream(String contentType) {
		return hasType(TYPE_STRATEGY.get(contentType), HttpContentType.APPLICATION_OCTET_STREAM);
	}
	
	/**	
	 * 	是否为XML
	 * 	
	 * 	@author Pan
	 * 	@param 	request	HttpServletRequest
	 * 	@return	boolean
	 */
	public static boolean isXml(HttpServletRequest request) {
		return isXml(request.getContentType());
	}
	
	/**	
	 * 	是否为XML
	 * 	
	 * 	@author Pan
	 * 	@param 	contentType	内容类型
	 * 	@return	boolean
	 */
	public static boolean isXml(String contentType) {
		return hasType(TYPE_STRATEGY.get(contentType), HttpContentType.APPLICATION_XML);
	}
	
	/**	
	 * 	是否为Ajax请求
	 * 	<br>true为是Ajax请求
	 * 
	 * 	@author Pan
	 *	@return	boolean
	 */
	public static boolean isAjax() {
		return ServletUtils.getHeader("X-Requested-With") != null;
	}
	
	/**	
	 * 	获取请求类型
	 * 	
	 * 	@author Pan
	 * 	@param 	request		HttpServletRequest对象
	 * 	@return	HttpContentType
	 */
	public static HttpContentType getType(HttpServletRequest request) {
		String contentType = request.getContentType();
		RequestContentStrategy content = TYPE_STRATEGY.get(contentType);
		
		if (content == null) {
			//	避免某些请求类型需要验证包含
			if (isFormData(contentType)) {
				return TYPE_STRATEGY.get(HttpContentType.MULTIPART_FORM_DATA.getType()).getContent();
			}
			//	防止不规范格式
			if (contentType.startsWith(HttpContentType.APPLICATION_JSON.getType())) {
				return TYPE_STRATEGY.get(HttpContentType.APPLICATION_JSON.getType()).getContent();
			}
			return HttpContentType.UNKNOWN;
		}
		return content.getContent();
	}
	
	/**	
	 * 	判断是否为指定类型
	 * 	<br>true为指定类型
	 * 	
	 * 	@author Pan
	 * 	@param 	type1		请求类型1
	 * 	@param 	type2		请求类型2
	 * 	@return	boolean
	 */
	private static boolean hasType(RequestContentStrategy type1, HttpContentType type2) {
		if (type1 == null) {
			return false;
		}
		return ObjectUtils.eq(type1.getContent(), type2);
	}
}
